import java.awt.BorderLayout;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Panel;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import processing.core.PApplet;



public class Framework implements TLModule{
	private static final int APP_SIZE_X = 1280;
	private static final int APP_SIZE_Y = 950;
	
	private Connection connection;
	
	//frames and panels
	private JFrame main;
	private JPanel north;
	private JPanel west;
	private JPanel center;
	private JPanel east;
	
	//states
	private JPanel stateLists;
	private JPanel stateSongs;
	private JPanel statePhrases;
	private JPanel stateUsers;
	
	//twitter lyrics modules (TLModules)
	private Graph graph = new Graph();
	private TimeSlider slider = new TimeSlider(this);
	private LogoPanel logo = new LogoPanel("TwitterLyrics_logo.png");
	private PopsongPanel popSong = new PopsongPanel(this);
	private PopQuotePanel popQuote = new PopQuotePanel(this);
	private HeatPanel heat = new HeatPanel(this);
	private TimeZoneMap timeZoneMap = new TimeZoneMap(0.7f);
	private TimeZoneMap timeZoneMapSmall = new TimeZoneMap(0.3f);
	private SongDisplayApplet songDisplayApplet = new SongDisplayApplet();
	private RatingChart ratingChart = new RatingChart();
	private ShowLyrics showLyrics = new ShowLyrics(this);
	private ShowTweets showTweets = new ShowTweets(this);
	private TwitterPopularity twitterPopularity = new TwitterPopularity();
	private CircleButtons buttons = new CircleButtons(this);

	
	public Framework(){
		//setup
		timeZoneMap.init();
		timeZoneMapSmall.init();
		graph.init();
		ratingChart.init();
		songDisplayApplet.init();
		twitterPopularity.init();
		
//		setDefaultValues();
		
		JFrame main = new JFrame("TwitterLyrics");
		main.setLayout(new BorderLayout());
		
		//create panels
		north = new JPanel();
		north.setBackground(Color.WHITE);
		west = new JPanel();
		west.setBackground(Color.WHITE);
		center = new JPanel();
		center.setBackground(Color.WHITE);
//		east = new JPanel();
		
		//fill the panels
		north.add(getPopular());
		west.add(getLeftPanels());		
		center.add(getStateLists());
		
		//add panels to main
		main.add(north, BorderLayout.NORTH);
		main.add(west, BorderLayout.WEST);
		main.add(center, BorderLayout.CENTER);
//		main.add(east, BorderLayout.EAST);
		
		//some needed stuff
		main.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		main.setSize(APP_SIZE_X, APP_SIZE_Y);
		main.setVisible(true);
				
		
		//experimental:
//		
//		while(true){
//			try {Thread.sleep(10000);} catch (Exception e) {}
//			songState();
//			try {Thread.sleep(3000);} catch (Exception e) {}
//			phraseState();
//			try {Thread.sleep(3000);} catch (Exception e) {}
//			userState();
//			try {Thread.sleep(3000);} catch (Exception e) {}
//			listState();
//		}
	}
	
	private void setDefaultValues() {
		//song
		List songId = new ArrayList<Long>();
		songId.add(1481);
		this.highlightSong(songId);
		
		//phrase
		List phraseId = new ArrayList<Long>();
		phraseId.add(1);
		this.highlightPhrase(phraseId);
		
		//user
		List users = new ArrayList<String>();
		users.add("Sx3inSC");
		this.highlightUser(users);
		
//		//time
//		long end = 1274280113871l;
//		this.setTimeSpan(new Timestamp(1), new Timestamp(end));
	}

	private Component getLeftPanels() {
		
		
		JPanel left = new JPanel();
		left.setBackground(Color.WHITE);
				
		
		JPanel west = new JPanel();
		west.setBackground(Color.WHITE);
		
		west.add(getSongList());
		west.add(slider);
//		west.add(new JButton("charts"));
		west.setPreferredSize(new Dimension(200, 400));
		
		left.add(west);
		
		
		left.add(buttons);
		
		left.setPreferredSize(new Dimension(250, 800));
//		
//		GridBagConstraints constraints = new GridBagConstraints();
//		
//		constraints.fill = GridBagConstraints.NONE;
//		constraints.weightx = 1.0;
//		constraints.weighty = 1.0;
//		
//		left.add(this.slider, constraints);
//		
//		constraints.gridheight = 3;
//		constraints.gridwidth = GridBagConstraints.REMAINDER;
//		left.add(getSongList(), constraints);
//		
//		constraints.gridheight = 1; //reset default
//		constraints.gridwidth = 1; //reset default
//		
//		left.add(new JButton("charts"), constraints);
//		left.add(new JButton("tabs"), constraints);		
	return left;
}

	/**
	 * puts the framework in the lists state
	 */
	public void listState(){
		center.removeAll();
		center.invalidate();		
		center.add(getStateLists());
		center.validate();
	}
	
	/**
	 * puts the framework in the song state
	 */
	public void songState(){
		center.removeAll();
		center.invalidate();		
		center.add(getStateSongs());
		center.validate();
	}

	/**
	 * puts the framework in the phrase state
	 */
	public void phraseState(){
		center.removeAll();
		center.invalidate();		
		center.add(getStatePhrases());
		center.validate();
	}
	
	/**
	 * puts the framework in the user state
	 */
	public void userState(){
		center.removeAll();
		center.invalidate();		
		center.add(getStateUsers());
		center.validate();
	}
	
	/**
	 * gives the panel for the center view of the state lists
	 * @return the panel
	 */
	private Component getStateLists() {
		if(stateLists != null)
			return stateLists;
		else{
			stateLists = new JPanel();
		
			stateLists.add(getRatingsDifference(), BorderLayout.NORTH);		
//			stateLists.add(getWelcomeMessage());
//			stateLists.add(getTwitterLyricsTop100());					
			stateLists.add(getWorldMap());	
			
			stateLists.setPreferredSize(new Dimension(800,800));
			stateLists.setBackground(Color.WHITE);
			
			return stateLists;
			}	
	}
	
	private Component getStateSongs() {
		if(stateSongs != null)			
			;
		else{
			stateSongs = new JPanel();
			stateSongs.setPreferredSize(new Dimension(800,800));
			stateSongs.setBackground(Color.WHITE);
//			stateSongs.setLayout(new GridLayout(1, 2));
					
			//upper panel
//			JPanel upper = new JPanel();
//			upper.setLayout(new GridLayout(1,2));
//			upper.add(getSongInfo());
//			upper.add(getSongRatingsChartVsLyrics());
			stateSongs.add(getSongInfo());
			
			//middle panel
//			JPanel middle = new JPanel();
//			middle.setLayout(new GridLayout(1,2));
//			middle.add(getSongPhrases());
//			middle.add(getSongRatingsChart());
			stateSongs.add(getSongPhrases());
			
			//lower panel
//			JPanel lower = new JPanel();
//			lower.setLayout(new GridLayout(1,2));
//			lower.add(new JLabel(""));
//			lower.add(getWorldMap());
			stateSongs.add(getWorldMap());
			
			
//			//Left
//			JPanel left = new JPanel();
//			left.setLayout(new GridLayout(3, 1));
//			left.add(getSongInfo());
//			left.add(getSongPhrases());
//			stateSongs.add(left);			
//			
//			//right		
//			JPanel right = new JPanel();
//			right.setLayout(new GridLayout(3, 1));
//			right.add(getSongRatingsChartVsLyrics());
//			right.add(getSongRatingsChart());
//			right.add(getWorldMap());
//			stateSongs.add(right);
		
			
			}
		stateSongs.revalidate();
		stateSongs.repaint();
		return stateSongs;
	}

	private Component getStatePhrases(){
		if(statePhrases != null)
			return statePhrases;
		else{
			statePhrases = new JPanel();
			statePhrases.setBackground(Color.WHITE);
//			statePhrases.setLayout(new GridBagLayout());
//			GridBagConstraints constraints = new GridBagConstraints();
//			
//			constraints.fill = GridBagConstraints.BOTH;
//			constraints.weightx = 1.0;		
//			
//			//top row
//			statePhrases.add(getPhraseInfo(), constraints);
//			constraints.gridwidth = GridBagConstraints.REMAINDER;
//			statePhrases.add(getPhraseVsSongRatings(), constraints);
//			
//			//rest
//			constraints.gridwidth = 1; //reset to default
//			constraints.gridheight = 2;
//			statePhrases.add(getTweets(), constraints);			
//			constraints.gridwidth = GridBagConstraints.REMAINDER;
//			constraints.gridheight = 1; //reset to default
//			statePhrases.add(getPhraseRatings(), constraints);
//			statePhrases.add(getWorldMap(), constraints);			
			statePhrases.setPreferredSize(new Dimension(800,800));
			
			statePhrases.add(getTweets());
			statePhrases.add(getWorldMap());
			
			
			return statePhrases;
		}		
	}
	
	private Component getStateUsers(){
		if(stateUsers != null)
			return stateUsers;
		else{
			stateUsers = new JPanel();
			stateUsers.setBackground(Color.WHITE);
			stateUsers.setLayout(new GridBagLayout());
			GridBagConstraints constraints = new GridBagConstraints();
			
			constraints.fill = GridBagConstraints.NONE;
			constraints.weightx = 1.0;
			constraints.weighty = 1.0;
		
			//rest			
			constraints.gridheight = 3;
			stateUsers.add(getGraph(), constraints);			
			constraints.gridwidth = GridBagConstraints.REMAINDER;
			constraints.gridheight = 1; //reset to default
			stateUsers.add(new JLabel(""), constraints);
			stateUsers.add(timeZoneMapSmall);			
			
			return stateUsers;
		}		
	}
	
	private Component getUserActivity() {
		// TODO Auto-generated method stub
		return new JButton("UserActivity");
	}

	private Component getTimeSlider() {
		return slider;
	}
	
	private Component getPhraseRatings() {
		// TODO Auto-generated method stub
		return new JButton("PhraseRatings");
	}

	private Component getTweets() {		
		return this.showTweets;
	}

	private Component getPhraseVsSongRatings() {
		// TODO Auto-generated method stub
		return new JButton("PhraseVsSongsRatings");
	}

	private Component getPhraseInfo() {
		// TODO Auto-generated method stub
		return new JButton("PhraseInfo");
	}

	private Component getSongRatingsChartVsLyrics() {
		// TODO Auto-generated method stub
		return new JButton("SongRatingsChartVsLyrics");
	}

	private Component getSongPhrases() {
		return this.showLyrics;
	}

	private Component getSongInfo() {
		return songDisplayApplet;
	}

	private Component getWorldMap() {
		return timeZoneMap;
	}

	private Component getSongRatingsChart() {
		return twitterPopularity;
	}

	private Component getTwitterLyricsTop100() {
		// TODO Auto-generated method stub
		return new JButton("TwitterLyricsTop100");
	}

	private Component getWelcomeMessage() {
		// TODO Auto-generated method stub
		return new JButton("WelcomeMessage");
	}

	private Component getRatingsDifference() {		
		return this.ratingChart;
	}

	private Component getPopular() {
		JPanel popular = new JPanel();
				
		popular.setBackground(new Color(203,204,206));
		popular.add(getLogoPanel());
		popular.add(getPopsongPanel());
		popular.add(getPopquotPanel());
		
		int y = getPopsongPanel().getPreferredSize().height + 20;
		Dimension d = new Dimension(this.APP_SIZE_X, y);
		popular.setPreferredSize(d);
		return popular;
	}
		

	private Component getLogoPanel() {
		return logo;
	}

	private Component getPopquotPanel() {		
		return popQuote;
	}

	private Component getPopsongPanel() {		
		return popSong;
	}

	private Component getSongList() {
		return heat;
	}

	/**
	 * Checks whether graph has been initialized. If not it will be. 
	 * @return The initialized graph.
	 */
	private Component getGraph() {
//		if (graph != null){
//			return graph;
//		}
//		else{
//			graph = new Graph();
//			graph.init();
//			while (graph.defaultSize&&!graph.finished){
//				try {Thread.sleep(5);}
//				catch (Exception e){}
//			}
//		graph.init();
			return graph;
//		}
	}

	private Component getCharts() {
		// TODO Auto-generated method stub
		return new JButton("Charts");
	}

	public void oldFramework(){
		JFrame frame = new JFrame("Embedded PApplet");
		frame.setResizable(false);
		frame.setLayout(new GridLayout(2,1));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		PApplet embed = new Graph();
		frame.add(embed);		
		embed.init();
		while (embed.defaultSize&&!embed.finished){
			try {Thread.sleep(5);}
			catch (Exception e){}
		}
		
		PApplet embed2 = new Graph();
		frame.add(embed2);		
		embed2.init();
		while (embed2.defaultSize&&!embed2.finished){
			try {Thread.sleep(5);} 
			catch (Exception e) {}
		}

		PApplet embed3 = new Graph();				
		embed3.init();

		//		frame.pack();
		frame.setSize(800, 800);
		frame.setVisible(true);

		
		try {Thread.sleep(2000);} catch (Exception e) {}
		frame.getContentPane().removeAll();
		frame.getContentPane().invalidate();
		frame.getContentPane().validate();
		frame.getContentPane().repaint();
		frame.setContentPane(embed3);
//		frame.add(embed);
		
		try {Thread.sleep(2000);} catch (Exception e) {}
		System.exit(0);
	}
	
	/**
	 * get's all modules that are used by the application
	 * @return the modules
	 */
	private TLModule[] getModules(){
		//TODO: add all other modules
		TLModule[] modules = {
				(TLModule) graph, 
				(TLModule) popSong,
				(TLModule) popQuote,
				(TLModule) heat,
				(TLModule) timeZoneMap,
				(TLModule) songDisplayApplet,
				(TLModule) ratingChart,
				(TLModule) showTweets,
				(TLModule) showLyrics,
				(TLModule) twitterPopularity
				
				};
		return modules;
	}
	
	/**
	 * passes the information to all other modules
	 */
	@Override
	public void highlightPhrase(List<Long> phraseId) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.highlightPhrase(phraseId);
			module.setPhrase(phraseId);
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void highlightSong(List<Long> songId) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.highlightSong(songId);
			//TEST:
			module.setSong(songId);
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void highlightUser(List<String> users) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.highlightUser(users);
			module.setUser(users);
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void reset() {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.reset();
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void resetPhrase() {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.resetPhrase();
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void resetSong() {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.resetSong();
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void resetTime() {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.resetTime();
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void resetUser() {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.resetUser();
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void setPhrase(List<Long> phraseId) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.setPhrase(phraseId);
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void setSong(List<Long> songId) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.setSong(songId);
		}		
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void setTimeSpan(Timestamp start, Timestamp end) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.setTimeSpan(start, end);
		}
	}

	/**
	 * passes the information to all other modules
	 */
	@Override
	public void setUser(List<String> users) {
		TLModule[] modules = getModules();
		for(TLModule module : modules){
			module.setUser(users);
		}
	}
	

	public static void main(String Args[]){
		Framework fw = new Framework();
	}

	@Override
	public void resetBillBoard(String chart_name) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setBillBoard(String chart_name) {
		// TODO Auto-generated method stub
		
	}
}
